#!/bin/sh
#
# Usage:
#   gnc-vcs-info -r <srcdir>
#   gnc-vcs-info -d <srcdir>
#   gnc-vcs-info -t <srcdir>
#
# With -r prints the revision number to stdout and exits 0 on success
# With -d prints the commit date to stdout and exits 0 on success
# With -t prints the vcs type that was detected to stdout and exits 0
#         on success.
#
# Exits with errorcode 1 if we're not in an bzr, svn, svk or git checkout
#
# Written By:  Derek Atkins <derek@ihtfp.com>
# Updated By:  Geert Janssens <geert@kobaltwit.be>
#
# $Id$

# Default string to return if not invoked properly
usage="Usage: $0 -r <srcdir>
       $0 -d <srcdir>
       $0 -t <srcdir>"

# Print an error message and then exit
my_die()
{
  echo "$1"
  exit 1
}

if [ "$BUILDING_FROM_VCS" = "0" -o \
     "$BUILDING_FROM_VCS" = "no" -o \
     "$BUILDING_FROM_VCS" = "false" ]; then
  # Something outside of the Gnucash build system knows that we
  # are NOT building from svn, svk or git checkout.
  # We should believe it (needed by packagers that maintain the
  # packaging code in svn, svk or git too)
  echo "Environment variable BUILDING_FROM_VCS=$BUILDING_FROM_VCS" >&2
  exit 1
fi

# Make sure we have a srcdir
[ -n "$1" ] || my_die "$usage"
[ -n "$2" ] || my_die "$usage"
[ -d "$2" ] || my_die "$0: $2: not a directory"


if [ "$1" = "-t" ]
then
  request="type"
elif [ "$1" = "-r" ]
then
  request="revision"
elif [ "$1" = "-d" ]
then
  request="date"
else
  my_die "$usage"
fi

srcdir=$2

# Find the real srcdir.
# This handles the case of a symlink (lndir) tree
# $real_srcdir will hold the actual source dir
if test -h "$srcdir"/Makefile.am
then 
  tmp_srcdir=`readlink "$srcdir"/Makefile.am`
  real_srcdir="$srcdir/`dirname ${tmp_srcdir}`"
else
  real_srcdir="$srcdir"
fi

# Test if this code is an SVN Checkout
#   If this is an svn checkout we assume you have svnversion!
if test -d "${real_srcdir}"/.svn
then
  # If we're only interested in the vcs type, then we're done here
  if [ "$request" = "type" ]
  then
    echo "svn"
    exit 0
  fi

  if [ "$request" = "date" ]
  then
    echo $(svn info "$real_srcdir}" | awk '/Last Changed Date/ { print $4 }')
    exit 0
  fi

  # svnversion without options returns the most recent revision in the repo
  # at the time of the last svn update/checkout even if that revision
  # didn't hold any changes in the current path. Not very useful as a
  # reference. Better is to ask for the last changed revision with -c.
  # BUT: -c option for some reason always considers svn working copy
  # as having mixed sources. We're only interested in the last part so
  # we strip the beginning revision if it's there.
  # As a result if your WC really has mixed sources, that will not be
  # visible in the version number...
  svn_mixed_version=$(svnversion -c "$real_srcdir")
  echo ${svn_mixed_version#*:}
  exit $?
fi

# If we get here then this is NOT an svn checkout.
# Maybe it's git?
real_gitdir="${real_srcdir}"/.git
if test -d "${real_gitdir}"
then
  # If we're only interested in the vcs type, then we're done here
  if [ "$request" = "type" ]
  then
    echo "git"
    exit 0
  fi

  # The windows build uses environment variable $GIT_CMD to invoke git (adding git
  # to the PATH in Windows results in a build failure).
  # So for platform independence, use GIT_CMD for all
  [ -n "$GIT_CMD" ] || GIT_CMD=git
  if [ "$request" = "date" ]
  then
    exec "$GIT_CMD" --git-dir "${real_gitdir}" log -1 --format=%cd --date=short
    exit 0
  fi

  githead=$("$GIT_CMD" --git-dir "${real_gitdir}" describe 2>/dev/null)
  rc=$?
  if [ $rc != 0 ]; then
    # On travis describe seems to fail due to missing tags in the git clone the system takes
    # So specifically to catch those errors, use only the short commit hash as a backup
    githead=$("$GIT_CMD" --git-dir "${real_gitdir}" log -1 --pretty=format:"%h" HEAD 2>/dev/null)
    rc=$?
  fi
  if [ $rc = 0 ]; then
    /bin/echo -n $githead
    # Add a "+" to the hash if there deleted or modified files (not excluded by .gitignore and friends)
    # "Ignores" untracked files
    # [ $("$GIT_CMD" --git-dir "${real_gitdir}" ls-files -dkm 2>/dev/null | wc -l) -gt 0 ] && /bin/echo -n "+"
    # Includes untracked files
    [ $("$GIT_CMD" --git-dir "${real_gitdir}" ls-files -dkmo --exclude-standard 2>/dev/null | wc -l) -gt 0 ] && /bin/echo -n "+"
    echo
    exit 0
  else
    exit 1
  fi
fi

if test -d "${real_srcdir}"/.bzr ;
then
  # If we're only interested in the vcs type, then we're done here
  if [ "$request" = "type" ]
  then
    echo "bzr"
    exit 0
  fi

  if [ "$request" = "date" ]
  then
    # FIXME Don't know how to extract the commit's date from a bzr commit...
    echo $(date +%Y-%m-%d)
    exit 0
  fi

  bzrhead=`(cd "${real_srcdir}"; bzr version-info --custom --template='{revno}\n')`
  if test $? = 0 ; then
    echo "$bzrhead";
    exit 0
  else
    exit 1
  fi
fi

if test $OSTYPE -a $OSTYPE = "msys";
then
  svk_name="svk.bat"
  svk_cmd="cmd \/c svk"
else
  svk_name="svk"
  svk_cmd="svk"
fi

# Maybe it's SVK?  First, check if we've got 'svk' in the path.  If not,
# then exit with an error code of 1..
which $svk_name >/dev/null 2>&1
if test $? != 0 ; then exit 1 ; fi

# Okay, we have 'svk'.  Now see if $real_srcdir is an svk checkout
# Note that the 'echo n' is to protect against having svk installed
# without having configured the depotmap.
svkinfo=`echo n | $svk_cmd info "$real_srcdir" 2>&1`
if test $? != 0 ; then exit 1 ; fi

# If we got here, then $real_srcdir is an svk checkout.
# If we're only interested in the vcs type, then we're done here
if [ "$request" = "type" ]
then
  echo "svk"
  exit 0
fi

if [ "$request" = "date" ]
then
  # FIXME Don't know how to extract the commit's date from an svk commit...
  echo $(date +%Y-%m-%d)
  exit 0
fi


# Parse out the revision info, print it out, and then output 0.  Just combine
# all the revision numbers into a single string by combining them
# with periods.
svkinfo=`$svk_cmd info "$real_srcdir" | grep Rev | head -5 | sed -e 's/^.* \([0-9:]*\)$/\1/'`
echo $svkinfo | sed -e 's/ /./g'

exit 0
